#ifndef UnstructMG_BOX_LU_HPP
#define UnstructMG_BOX_LU_HPP

#include "par_CSRMatrix.hpp"
#include "direct_solver.hpp"


template<typename idx_t, typename data_t, typename setup_t, typename calc_t, int dof>
class BoxLU final : public Solver<idx_t, setup_t, calc_t, dof> {
public:
    BoxLU();
    ~BoxLU();
    void SetOperator(const Operator<idx_t, setup_t, dof> & op);
private:
    bool own_A = false;
    const par_CSRMatrix<idx_t, data_t, calc_t, dof> * A_calc = nullptr;// setup时需要截断的低精度矩阵
    CSR_sparseMat<idx_t, calc_t, calc_t> * locA_csr = nullptr;// 如果用的稀疏，存储直接法求解器的句柄

    void factorize(const CSRMatrix<idx_t, setup_t, setup_t, dof> & A);
    seq_Vector<idx_t, calc_t, dof> * aux = nullptr;

protected:
    void truncate();
    void Mult_ipl(const par_Vector<idx_t, calc_t, dof> & input, par_Vector<idx_t, calc_t, dof> & output) const ;
};

typedef BoxLU<int, double, double, double, 1> BoxLU_I32All64_DOF1;
typedef BoxLU<int, double, double, double, 2> BoxLU_I32All64_DOF2;
typedef BoxLU<int, double, double, double, 3> BoxLU_I32All64_DOF3;
typedef BoxLU<int, double, double, double, 4> BoxLU_I32All64_DOF4;

typedef BoxLU<int, float , double, double, 1> BoxLU_I32K64P64D32_DOF1;
typedef BoxLU<int, float , double, double, 2> BoxLU_I32K64P64D32_DOF2;
typedef BoxLU<int, float , double, double, 3> BoxLU_I32K64P64D32_DOF3;
typedef BoxLU<int, float , double, double, 4> BoxLU_I32K64P64D32_DOF4;

typedef BoxLU<int, float , double, float , 1> BoxLU_I32K64P32D32_DOF1;
typedef BoxLU<int, float , double, float , 2> BoxLU_I32K64P32D32_DOF2;
typedef BoxLU<int, float , double, float , 3> BoxLU_I32K64P32D32_DOF3;
typedef BoxLU<int, float , double, float , 4> BoxLU_I32K64P32D32_DOF4;

typedef BoxLU<int, float , float , float , 1> BoxLU_I32All32_DOF1;
typedef BoxLU<int, float , float , float , 2> BoxLU_I32All32_DOF2;
typedef BoxLU<int, float , float , float , 3> BoxLU_I32All32_DOF3;
typedef BoxLU<int, float , float , float , 4> BoxLU_I32All32_DOF4;
#ifdef USE_FP16
typedef BoxLU<int, __fp16, double, float , 1> BoxLU_I32K64P32D16_DOF1;
typedef BoxLU<int, __fp16, double, float , 2> BoxLU_I32K64P32D16_DOF2;
typedef BoxLU<int, __fp16, double, float , 3> BoxLU_I32K64P32D16_DOF3;
typedef BoxLU<int, __fp16, double, float , 4> BoxLU_I32K64P32D16_DOF4;

typedef BoxLU<int, __fp16, float , float , 1> BoxLU_I32K32P32D16_DOF1;
typedef BoxLU<int, __fp16, float , float , 2> BoxLU_I32K32P32D16_DOF2;
typedef BoxLU<int, __fp16, float , float , 3> BoxLU_I32K32P32D16_DOF3;
typedef BoxLU<int, __fp16, float , float , 4> BoxLU_I32K32P32D16_DOF4;
#endif

#endif